package com.chilly.other.thread;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * CountDownLatch基于AQS实现，volatile变量state维持倒数状态，多线程共享变量可见。
 *
 * CountDownLatch 在多线程下：等待所有子线程全部执行完毕之后再做操作
 *
 * 举个例子，早上部门开会，有人在上厕所，这时候需要等待所有人从厕所回来之后才能开始会议。
 * https://mp.weixin.qq.com/s/LDNQMCBXuUfv5ePG0PQUFw
 *
 * Created by Chilly Cui on 2020/12/11.
 */
public class CountDownLatchDemoMeeting {
    private static  int num = 3;
    private static ExecutorService executorService = Executors.newFixedThreadPool(num);
    private static CountDownLatch latch = new CountDownLatch(num);

    public static void main(String[] args) throws InterruptedException {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("A 在上厕所");
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    latch.countDown();
                    System.out.println("A 上完了");
                }
            }
        });

        executorService.submit(() -> {
            System.out.println("B 在上厕所");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                latch.countDown();
                System.out.println("B 上完了");
            }
        });

        executorService.submit(()->{
            System.out.println("C在上厕所");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                latch.countDown();
                System.out.println("C上完了");
            }
        });

        System.out.println("人到齐了再开会，等待中。。。。");

        latch.await();
        System.out.println("所有人都好了，开始开会...");
        executorService.shutdown();

    }
}
